"""
日志装饰器模块
提供自动日志记录功能
"""

import time
import traceback
import json
from functools import wraps
from flask import request, g
from flask_login import current_user
import uuid

from services.shared.log_utils import log_user_action, log_system_event


def log_function_call(level='INFO', module=None, action=None, resource_type=None, 
                     include_args=False, include_result=False, log_errors=True):
    """
    函数调用日志装饰器
    
    Args:
        level: 日志级别
        module: 模块名称（默认使用函数所在模块）
        action: 操作类型（默认使用函数名）
        resource_type: 资源类型
        include_args: 是否记录函数参数
        include_result: 是否记录函数返回值
        log_errors: 是否记录异常
    """
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            
            # 生成请求ID
            request_id = str(uuid.uuid4())
            
            # 确定模块名称
            func_module = module or func.__module__
            
            # 确定操作类型
            func_action = action or func.__name__
            
            # 准备详细信息
            details = {
                'function': func.__name__,
                'module': func.__module__,
            }
            
            if include_args:
                details['args'] = str(args)[:500]  # 限制长度
                details['kwargs'] = str(kwargs)[:500]
            
            try:
                # 执行函数
                result = func(*args, **kwargs)
                
                # 计算执行时间
                execution_time = (time.time() - start_time) * 1000
                
                if include_result:
                    details['result'] = str(result)[:500]
                
                # 记录成功日志
                log_user_action(
                    level=level,
                    module=func_module,
                    message=f'函数 {func.__name__} 执行成功',
                    details=json.dumps(details, ensure_ascii=False),
                    action=func_action,
                    resource_type=resource_type,
                    execution_time=execution_time,
                    status_code=200,
                    request_id=request_id,
                    tags=['function_call', 'success']
                )
                
                return result
                
            except Exception as e:
                # 计算执行时间
                execution_time = (time.time() - start_time) * 1000
                
                if log_errors:
                    details['error'] = str(e)
                    details['error_type'] = type(e).__name__
                    
                    # 记录错误日志
                    log_user_action(
                        level='ERROR',
                        module=func_module,
                        message=f'函数 {func.__name__} 执行失败: {str(e)}',
                        details=json.dumps(details, ensure_ascii=False),
                        action=func_action,
                        resource_type=resource_type,
                        execution_time=execution_time,
                        status_code=500,
                        request_id=request_id,
                        severity=5,
                        error_code=type(e).__name__,
                        stack_trace=traceback.format_exc(),
                        tags=['function_call', 'error']
                    )
                
                raise
                
        return wrapper
    return decorator


def log_api_endpoint(resource_type=None, action=None):
    """
    API端点日志装饰器
    
    Args:
        resource_type: 资源类型
        action: 操作类型
    """
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            
            # 生成请求ID
            request_id = str(uuid.uuid4())
            g.request_id = request_id
            
            # 获取请求信息
            endpoint = request.endpoint or func.__name__
            method = request.method
            url = request.url
            
            # 获取请求大小
            request_size = len(request.get_data()) if request.get_data() else 0
            
            try:
                # 执行函数
                result = func(*args, **kwargs)
                
                # 计算执行时间
                execution_time = (time.time() - start_time) * 1000
                
                # 确定状态码
                status_code = 200
                if hasattr(result, 'status_code'):
                    status_code = result.status_code
                elif isinstance(result, tuple) and len(result) > 1:
                    status_code = result[1]
                
                # 获取响应大小
                response_size = 0
                if hasattr(result, 'content_length') and result.content_length:
                    response_size = result.content_length
                
                # 记录API调用日志
                log_user_action(
                    level='INFO' if status_code < 400 else 'WARNING',
                    module='api',
                    message=f'{method} {endpoint} - {status_code}',
                    action=action or 'api_request',
                    resource_type=resource_type or 'api',
                    resource_id=endpoint,
                    execution_time=execution_time,
                    status_code=status_code,
                    request_id=request_id,
                    request_method=method,
                    request_url=url,
                    response_size=response_size,
                    severity=0 if status_code < 400 else 2,
                    tags=['api', method.lower()]
                )
                
                return result
                
            except Exception as e:
                # 计算执行时间
                execution_time = (time.time() - start_time) * 1000
                
                # 记录API错误日志
                log_user_action(
                    level='ERROR',
                    module='api',
                    message=f'{method} {endpoint} - 500 - {str(e)}',
                    action=action or 'api_request',
                    resource_type=resource_type or 'api',
                    resource_id=endpoint,
                    execution_time=execution_time,
                    status_code=500,
                    request_id=request_id,
                    request_method=method,
                    request_url=url,
                    severity=5,
                    error_code=type(e).__name__,
                    stack_trace=traceback.format_exc(),
                    tags=['api', method.lower(), 'error']
                )
                
                raise
                
        return wrapper
    return decorator


def log_task_operation(task_id=None, task_name=None):
    """
    任务操作日志装饰器
    
    Args:
        task_id: 任务ID
        task_name: 任务名称
    """
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            
            # 生成请求ID
            request_id = str(uuid.uuid4())
            
            # 尝试从参数中获取任务信息
            actual_task_id = task_id
            actual_task_name = task_name
            
            if not actual_task_id and args:
                # 尝试从第一个参数获取任务ID
                if hasattr(args[0], 'id'):
                    actual_task_id = args[0].id
                elif isinstance(args[0], (int, str)):
                    actual_task_id = args[0]
            
            if not actual_task_name and args:
                # 尝试从第一个参数获取任务名称
                if hasattr(args[0], 'name'):
                    actual_task_name = args[0].name
                elif hasattr(args[0], 'task_name'):
                    actual_task_name = args[0].task_name
            
            try:
                # 执行函数
                result = func(*args, **kwargs)
                
                # 计算执行时间
                execution_time = (time.time() - start_time) * 1000
                
                # 记录任务操作日志
                log_user_action(
                    level='INFO',
                    module='task_manager',
                    message=f'任务操作 {func.__name__} 成功',
                    action=func.__name__,
                    resource_type='task',
                    resource_id=str(actual_task_id) if actual_task_id else None,
                    execution_time=execution_time,
                    status_code=200,
                    request_id=request_id,
                    tags=['task', func.__name__]
                )
                
                return result
                
            except Exception as e:
                # 计算执行时间
                execution_time = (time.time() - start_time) * 1000
                
                # 记录任务操作错误日志
                log_user_action(
                    level='ERROR',
                    module='task_manager',
                    message=f'任务操作 {func.__name__} 失败: {str(e)}',
                    action=func.__name__,
                    resource_type='task',
                    resource_id=str(actual_task_id) if actual_task_id else None,
                    execution_time=execution_time,
                    status_code=500,
                    request_id=request_id,
                    severity=5,
                    error_code=type(e).__name__,
                    stack_trace=traceback.format_exc(),
                    tags=['task', func.__name__, 'error']
                )
                
                raise
                
        return wrapper
    return decorator


def log_database_operation(table_name=None, operation=None):
    """
    数据库操作日志装饰器
    
    Args:
        table_name: 表名
        operation: 操作类型
    """
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            
            try:
                # 执行函数
                result = func(*args, **kwargs)
                
                # 计算执行时间
                execution_time = (time.time() - start_time) * 1000
                
                # 记录数据库操作日志
                log_system_event(
                    level='DEBUG' if execution_time < 100 else 'INFO',
                    module='database',
                    message=f'数据库操作 {func.__name__} 完成',
                    action=operation or func.__name__,
                    resource_type='table',
                    resource_id=table_name,
                    execution_time=execution_time,
                    severity=1 if execution_time > 1000 else 0,
                    tags=['database', operation or func.__name__]
                )
                
                return result
                
            except Exception as e:
                # 计算执行时间
                execution_time = (time.time() - start_time) * 1000
                
                # 记录数据库操作错误日志
                log_system_event(
                    level='ERROR',
                    module='database',
                    message=f'数据库操作 {func.__name__} 失败: {str(e)}',
                    action=operation or func.__name__,
                    resource_type='table',
                    resource_id=table_name,
                    execution_time=execution_time,
                    severity=5,
                    error_code=type(e).__name__,
                    stack_trace=traceback.format_exc(),
                    tags=['database', operation or func.__name__, 'error']
                )
                
                raise
                
        return wrapper
    return decorator